﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Configuration.Provider;
using System.Web;
using System.Web.Configuration;
using System.Collections.ObjectModel;
using SCRUM.Core.DataProviders;

namespace SCRUM.Core.MembershipProviders
{
    /// <summary>
    /// Factory - decides which provider to use based on informations from web.config 
    /// </summary>
    public static class MembershipProviderFactory
    {
        /// <summary>
        /// Membership data provider
        /// </summary>
        private static MembershipDataProvider membershipProvider;

        /// <summary>
        /// Membership data provider collection from web config
        /// </summary>
        private static MembershipDataProviderCollection membershipProviders;

        /// <summary>
        /// Role data provider
        /// </summary>
        private static RoleDataProvider roleProvider;

        /// <summary>
        /// Role data provider collection from web config
        /// </summary>
        private static RoleDataProviderCollection roleProviders;

        /// <summary>
        /// Lock object
        /// </summary>
        private static object lockObject = new object();

        /// <summary>
        /// Gets the current provider.
        /// </summary>
        public static MembershipDataProvider MembershipProvider
        {
            get 
            { 
                LoadProviders(); 
                return membershipProvider; 
            }
        }

        /// <summary>
        /// Gets a collection of all registered providers.
        /// </summary>
        public static MembershipDataProviderCollection MembershipProviders
        {
            get 
            { 
                LoadProviders(); 
                return membershipProviders; 
            }
        }

        /// <summary>
        /// Gets the current provider.
        /// </summary>
        public static RoleDataProvider RoleProvider
        {
            get
            {
                LoadProviders();
                return roleProvider;
            }
        }

        /// <summary>
        /// Gets a collection of all registered providers.
        /// </summary>
        public static RoleDataProviderCollection RoleProviders
        {
            get
            {
                LoadProviders();
                return roleProviders;
            }
        }

        /// <summary>
        /// Load the providers from the web.config.
        /// </summary>
        public static void LoadProviders()
        {
            // Avoid claiming lock if providers are already loaded
            if (membershipProvider == null)
            {
                lock (lockObject)
                {
                    // Do this again to make sure _provider is still null
                    if (membershipProvider == null)
                    {
                        // Get a reference to the membershipprovider section
                        MembershipDataProviderSection section = (MembershipDataProviderSection)WebConfigurationManager.GetSection("DataEngine/membershipDataProvider");

                        // Load registered providers and point _provider
                        // to the default provider
                        membershipProviders = new MembershipDataProviderCollection();
                        ProvidersHelper.InstantiateProviders(section.Providers, membershipProviders, typeof(MembershipDataProvider));
                        membershipProvider = membershipProviders[section.DefaultProvider];

                        if (membershipProvider == null)
                        {
                            throw new ProviderException("Unable to load default MembershipDataProvider");
                        }


                        // Get a reference to the role provider section
                        RoleDataProviderSection rsection = (RoleDataProviderSection)WebConfigurationManager.GetSection("DataEngine/roleDataProvider");

                        // Load registered providers and point _provider
                        // to the default provider
                        roleProviders = new RoleDataProviderCollection();
                        ProvidersHelper.InstantiateProviders(rsection.Providers, roleProviders, typeof(RoleDataProvider));
                        roleProvider = roleProviders[rsection.DefaultProvider];

                        if (roleProvider == null)
                        {
                            throw new ProviderException("Unable to load default RoleDataProvider");
                        }
                    }
                }
            }
        }
    }
}
